#include <iostream>
#include <sys/select.h>
#include "Sock.hpp"

int fdsArray[sizeof(fd_set) * 8] = {0};
int gnum = sizeof(fdsArray) / sizeof(fdsArray[0]);

#define DFL -1

using namespace std;

static void showArray(int arr[], int num)
{
    cout << "当前合法sock list# ";
    for(int i = 0; i < num; ++i)
    {
        if(arr[i] == DFL) continue;
        else cout << arr[i] << ' ';
    }
    cout << endl;
}

static void Usage(std::string process)
{
    cerr << "\nUsage: " << process << " port\n" << endl;
}

static void HandlerEvent(int listensock, fd_set &readfds)
{
    for(int i = 0; i < gnum; ++i)
    {
        if(fdsArray[i] == DFL) continue;

        if(i == 0 && fdsArray[i] == listensock)
        {
            if(FD_ISSET(listensock, &readfds))
            {
                cout << "已经有了一个新链接到了，需要进行获取(读取/拷贝)了" << endl;
                string clientip;
                uint16_t clientport = 0;
                int sock = Sock::Accept(listensock, &clientip, &clientport);
                if(sock < 0) return;
                cout << "获取新链接成功 : " << clientip << ":" << clientport << " | sock: " << sock << endl;

                int i = 0;
                for(; i < gnum; ++i)
                {
                    if(fdsArray[i] == DFL)
                    {
                        break;
                    }
                }

                if(i == gnum)
                {
                    cerr << "我的服务器已经到了最大的上限了，无法在承载更多同时保持的连接了" << endl;
                    close(sock);
                }
                else
                {
                    fdsArray[i] = sock;
                    showArray(fdsArray, gnum);
                }
            }
        }
        else
        {
            if(FD_ISSET(fdsArray[i], &readfds))
            {
                char buffer[1024];
                ssize_t s = recv(fdsArray[i], buffer, sizeof(buffer), 0);
                if(s > 0)
                {
                    buffer[s] = 0;
                    cout << "client[" << fdsArray[i] << "]# " << buffer << endl;
                }
                else if(s == 0)
                {
                    cout << "client[" << fdsArray[i] << "] quit, server close " << fdsArray[i] << endl;
                    close(fdsArray[i]);
                    fdsArray[i] = DFL;
                    showArray(fdsArray, gnum);
                }
                else
                {
                    cout << "client[" << fdsArray[i] << "] error, server close " << fdsArray[i] << endl;
                    close(fdsArray[i]);
                    fdsArray[i] = DFL;
                    showArray(fdsArray, gnum);
                }
            }
        }
    }
}

int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        Usage(argv[0]);
        exit(1);
    }

    int listensock = Sock::Socket();
    Sock::Bind(listensock, atoi(argv[1]));
    Sock::Listen(listensock);

    for(int i = 0; i < gnum; ++i)
    {
        fdsArray[i] = DFL;
    }
    fdsArray[0] = listensock;

    while(true)
    {
        int maxFd = DFL;
        fd_set readfds;
        FD_ZERO(&readfds);
        for(int i = 0; i < gnum; ++i)
        {
            if(fdsArray[i] == DFL) continue;
            FD_SET(fdsArray[i], &readfds);
            if(maxFd < fdsArray[i]) maxFd = fdsArray[i];
        }

        struct timeval timeout = {100, 0};
        int n = select(maxFd + 1, &readfds, nullptr, nullptr, &timeout);
        switch(n)
        {
        case 0:
            cout << "time out ... : " << (unsigned long)time(nullptr) << endl;
        case -1:
            cerr << errno << " : " << strerror(errno) << endl;
        default:
            HandlerEvent(listensock, readfds);
            break; 
        }
    }
    
    return 0;
}